using System;
using CKS.EBE.API;
using Microsoft.SharePoint;
using System.Diagnostics;

namespace CKS.EBE
{
    /// <summary>
    /// Installs the elements needed for storing trackbacks and pingbacks on 
    /// a blog site
    /// </summary>
    public static class LinkbackListsSetup
    {
        public static void AddLists(SPWeb blogWeb)
        {
            Debug.WriteLine("Installing Linkback Lists");

            try
            {
                SPWeb oWeb = blogWeb;
                
                // add Linkbacks Received list
                SPList oLinkbacksReceivedList = null;
                try { oLinkbacksReceivedList = oWeb.Lists["Linkbacks Received"]; }
                catch { }

                SPList oPostsList = Helper.GetListByFolderName(oWeb, Localization.GetListName(Localization.BlogList.Posts, oWeb.Language));
                SPFieldCollection oPostFields = oPostsList.Fields;

                if (oLinkbacksReceivedList == null)
                {
                    oLinkbacksReceivedList = AddLinkbacksReceivedList(oWeb, oLinkbacksReceivedList, oPostsList);
                }
                else
                {
                    // rename the list, so it can be found later. sometimes renaming the list did not work after createing it
                    oLinkbacksReceivedList.Title = "Linkbacks Received";
                    oLinkbacksReceivedList.Update();
                }
                
                // add Linkback count to Posts list
                SPField oLinkbacksCountField = null;
                try 
                { 
                    oLinkbacksCountField = oPostFields.GetFieldByInternalName("NumLinkbacks");
                }
                catch { }
                if (oLinkbacksCountField == null)
                {
                    oLinkbacksCountField = CreateLinkbacksCountField(oPostsList, oLinkbacksReceivedList);
                }

                // add manual trackback ping field to Posts list
                SPField oManualTrackbackPingField = null;
                try
                {
                    oManualTrackbackPingField = oPostFields.GetFieldByInternalName("ManualTrackbackPing");
                }
                catch { }
                if (oManualTrackbackPingField == null)
                {
                    oManualTrackbackPingField = CreateManualTrackbackPingField(oPostsList);
                }

                // add Linkbacks Sent list
                SPList oLinkbacksSentList = null;
                try { oLinkbacksSentList = oWeb.Lists["Linkbacks Sent"]; }
                catch { }
                if (oLinkbacksSentList == null)
                {
                    oLinkbacksSentList = AddLinkbacksSentList(oWeb, oLinkbacksSentList, oPostsList);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                throw;
            }
        }

        #region AddLists

        private static SPList AddLinkbacksReceivedList(SPWeb oWeb, SPList oLinkbacksList, SPList oPostsList)
        {
            Debug.WriteLine("Adding Linkbacks Received list");

            // if the list has not been renamed, try to get it by its name first
            try
            {
                oLinkbacksList = oWeb.Lists["LinkbacksReceived"];
            }
            catch{}

            if (oLinkbacksList == null)
            {
                Guid id = oWeb.Lists.Add(
                    "LinkbacksReceived",
                    "A list of trackbacks and pingbacks automatically captured when bloggers wrote about entries here in this blog.",
                    SPListTemplateType.GenericList);
                oLinkbacksList = oWeb.Lists[id];
            }
            oLinkbacksList.EnableModeration = true;
            oLinkbacksList.OnQuickLaunch = true;
            oLinkbacksList.WriteSecurity = 4;

            AddLinkbackFields(oLinkbacksList, oPostsList);
            AddLinkbackReceivedFields(oLinkbacksList);

            oLinkbacksList.Title = "Linkbacks Received";
            oLinkbacksList.Update();

            return oLinkbacksList;
        }

        private static SPList AddLinkbacksSentList(SPWeb oWeb, SPList oLinkbacksList, SPList oPostsList)
        {
            Debug.WriteLine("Adding Linkbacks Sent list");

            // if the list has not been renamed, try to get it by its name first
            try
            {
                oLinkbacksList = oWeb.Lists["LinkbacksSent"];
            }
            catch{}
            
            if (oLinkbacksList == null)
            {
                Guid id = oWeb.Lists.Add(
                    "LinkbacksSent",
                    "This list keeps a record of the trackbacks and pingbacks that were automatically or manually sent from this blog to others.",
                    SPListTemplateType.GenericList);
                oLinkbacksList = oWeb.Lists[id];
            }
            oLinkbacksList.EnableModeration = false;
            oLinkbacksList.OnQuickLaunch = true;
            oLinkbacksList.WriteSecurity = 4;

            AddLinkbackFields(oLinkbacksList, oPostsList);

            AddLinkbackSentFields(oLinkbacksList);

            oLinkbacksList.Title = "Linkbacks Sent";
            oLinkbacksList.Update();

            return oLinkbacksList;
        }

        #endregion

        #region AddFields

        /// <summary>
        /// Creates a field in the posts list that displays the number of related linkbacks for a 
        /// given post
        /// </summary>
        /// <param name="oPostsList"></param>
        /// <param name="oLinkbacksList"></param>
        /// <returns></returns>
        private static SPField CreateLinkbacksCountField(SPList oPostsList, SPList oLinkbacksList)
        {
            Debug.Write("Create Linkbacks count field");

            SPFieldLookup oField = (SPFieldLookup)oPostsList.Fields[oPostsList.Fields.AddLookup("NumLinkbacks", oLinkbacksList.ID, false)];
            oField.LookupField = "PostTitle";
            oField.CountRelated = true;
            oField.Title = "# Linkbacks";
            oField.ReadOnlyField = true;
            oField.Update();

            SPView view = oPostsList.DefaultView;
            SPViewFieldCollection viewFields = view.ViewFields;
            viewFields.Add(oField);

            view.Update();

            return oField;
        }

        private static SPField CreateManualTrackbackPingField(SPList oPostsList)
        {
            Debug.Write("Create Manual Trackback Ping field");

            SPField oField = oPostsList.Fields[oPostsList.Fields.Add("ManualTrackbackPing", SPFieldType.Note, false)];
            oField.Title = "Trackback ping URLs";
            oField.Description = "Trackback pings should be performed automatically. However, you can manually add trackback ping URLs here (one URL per line).";
            oField.Update();

            return oField;
        }

        /// <summary>
        /// Adds generic fields to linkback lists
        /// </summary>
        /// <param name="oLinkbacksList"></param>
        /// <param name="oPostsList"></param>
        private static void AddLinkbackFields(SPList oLinkbacksList, SPList oPostsList)
        {
            SPView view = oLinkbacksList.DefaultView;
            SPViewFieldCollection viewFields = view.ViewFields;

            SPField postTitle = CreatePostTitleLookupField(oLinkbacksList, oPostsList);
            viewFields.Add(postTitle);

            viewFields.Add(CreateField(oLinkbacksList, "LinkbackType", "Linkback Type", SPFieldType.Text, true));

            view.Update();
        }

        /// <summary>
        /// Adds fields specific to the Linkbacks Received List
        /// </summary>
        /// <param name="oLinkbacksList"></param>
        private static void AddLinkbackReceivedFields(SPList oLinkbacksList)
        {
            SPView view = oLinkbacksList.DefaultView;
            SPViewFieldCollection viewFields = view.ViewFields;

            viewFields.Add(CreateField(oLinkbacksList, "BlogName", Localization.GetResource("FieldTitle_BlogName", SPContext.Current.Web.Language), SPFieldType.Text, false));
            viewFields.Add(CreateField(oLinkbacksList, "LinkingPost", Localization.GetResource("FieldTitle_LinkingPost", SPContext.Current.Web.Language), SPFieldType.URL, false));
            viewFields.Add(CreateField(oLinkbacksList, "LinkingPostExcerpt", Localization.GetResource("FieldTitle_LinkingPostExcerpt", SPContext.Current.Web.Language), SPFieldType.Note, false));

            view.Update();
        }

        /// <summary>
        /// Adds fields specific to the Linkbacks Sent List
        /// </summary>
        /// <param name="oLinkbacksList"></param>
        private static void AddLinkbackSentFields(SPList oLinkbacksList)
        {
            SPView view = oLinkbacksList.DefaultView;
            SPViewFieldCollection viewFields = view.ViewFields;

            viewFields.Add(CreateField(oLinkbacksList, "SentToUrl", Localization.GetResource("FieldTitle_SentToUrl", SPContext.Current.Web.Language), SPFieldType.Text, false));
            viewFields.Add(CreateField(oLinkbacksList, "PingUrl", Localization.GetResource("FieldTitle_PingUrl", SPContext.Current.Web.Language), SPFieldType.Text, false));
            viewFields.Add(CreateField(oLinkbacksList, "SendResult", Localization.GetResource("FieldTitle_SendResult", SPContext.Current.Web.Language), SPFieldType.Text, false));
            viewFields.Add(CreateField(oLinkbacksList, "SendErrorMessage", Localization.GetResource("FieldTitle_SendErrorMessage", SPContext.Current.Web.Language), SPFieldType.Text, false));

            view.Update();
        }

        /// <summary>
        /// Helper method to create a field in a given list
        /// </summary>
        /// <param name="oLinkbackList"></param>
        /// <param name="title"></param>
        /// <param name="displayName"></param>
        /// <param name="fieldType"></param>
        /// <param name="required"></param>
        /// <returns></returns>
        private static SPField CreateField(SPList oLinkbackList, string title, string displayName, SPFieldType fieldType, bool required)
        {
            Debug.Write("  Creating " + title + " field");

            SPField oField = oLinkbackList.Fields[oLinkbackList.Fields.Add(title, fieldType, required)];
            oField.Title = displayName;
            oField.Update();

            return oField;
        }

        /// <summary>
        /// Create a lookup field in a linkbacks list that displays a list of posts
        /// </summary>
        /// <param name="oLinkbackList"></param>
        /// <param name="oPostList"></param>
        /// <returns></returns>
        private static SPField CreatePostTitleLookupField(SPList oLinkbackList, SPList oPostList)
        {
            try
            {
                // if the field exists, return it
                return oLinkbackList.Fields.GetFieldByInternalName("PostTitle");
            }
            catch (Exception)
            {
                // field does not exist
                Debug.Write("  Create Post Title lookup field");

                var oField = (SPFieldLookup) oLinkbackList.Fields[oLinkbackList.Fields.AddLookup("PostTitle", oPostList.ID, true)];
                oField.LookupField = "Title";
                oField.Title = Localization.GetResource("FieldTitle_PostTitle", SPContext.Current.Web.Language);
                oField.Update();

                return oField;
            }
        }
        #endregion
    }
}

